package com.lyf.scm.admin.domain.remote.basedata.facade;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.lyf.scm.admin.domain.remote.basedata.BaseDataRemote;
import com.lyf.scm.admin.domain.remote.basedata.dto.*;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.ResponseMsg;
import com.lyf.scm.common.model.SalesPlanSelectDTO;
import com.rome.arch.core.clientobject.Response;
import com.rome.arch.core.exception.RomeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 基本数据
 *
 * @author wuzhuang
 * @date 2020/07/14
 */
@Service
@Slf4j
public class BaseDataFacade {

    @Resource
    private BaseDataRemote baseDataRemote;

    /**
     * 根据父渠道批量获取下级渠道
     *
     * @param channelCodeList
     * @return
     */
    public List<SalesPlanSelectDTO> getSubChannelCode(List<SalesPlanSelectDTO> channelCodeList) {
        log.info("根据父渠道批量获取下级渠道：channelCodeList：{}", channelCodeList);
        if (CollectionUtils.isEmpty(channelCodeList)) {
            return null;
        }
        //对参数集合进行分组，分组后如果size为1，直接返回
        Map<Integer, List<SalesPlanSelectDTO>> listMap = channelCodeList.stream().collect(Collectors.groupingBy(SalesPlanSelectDTO::getLevel));
        final int reqSize = 1;
        //map长度大于1表示该查询条件携带层级不同的参数,渠道最多至2级；
        if (listMap.size() > reqSize) {
            // 获取最低层级的参数
            List<SalesPlanSelectDTO> leafCodeList = channelCodeList.stream().filter(item -> item.getLevel().equals(CommonConstants.CHANNEL_LEVEL_TOW)).collect(Collectors.toList());
            //获取渠道level为1的对象集，调用基础中心获取下级集合
            List<SalesPlanSelectDTO> paramCodeList = channelCodeList.stream().filter(item -> item.getLevel().equals(CommonConstants.CHANNEL_LEVEL_ONE)).collect(Collectors.toList());
            List<String> param = paramCodeList.stream().map(SalesPlanSelectDTO::getCode).collect(Collectors.toList());
            List<ChannelDTO> channelDTOS = this.queryByParentChannels(param);
            channelDTOS.forEach(item -> {
                SalesPlanSelectDTO selectDTO = new SalesPlanSelectDTO();
                selectDTO.setName(item.getChannelName());
                selectDTO.setCode(item.getChannel());
                selectDTO.setLevel(item.getLevel());
                leafCodeList.add(selectDTO);
            });
            return leafCodeList;
        }
        return channelCodeList;
    }

    /**
     * 根据父区域获取下级区域
     *
     * @param areaCodeList
     * @return
     */
    public List<SalesPlanSelectDTO> getSubAreaCode(List<SalesPlanSelectDTO> areaCodeList) {
        log.info("根据父区域获取下级区域：areaCodeList：{}", areaCodeList);
        if (CollectionUtils.isEmpty(areaCodeList)) {
            return null;
        }
        //对参数集合进行分组，分组后如果size为1，直接返回
        Map<Integer, List<SalesPlanSelectDTO>> listMap = areaCodeList.stream().collect(Collectors.groupingBy(SalesPlanSelectDTO::getLevel));
        final int reqSize = 1;
        //map长度大于1表示该查询条件携带层级不同的参数，区域有四层level；
        if (listMap.size() > reqSize) {
            // 获取最低级level值
            int subLevel = areaCodeList.stream().mapToInt(SalesPlanSelectDTO::getLevel).max().getAsInt();
            // 获取level最低的对象集
            List<SalesPlanSelectDTO> leafCodeList = areaCodeList.stream().filter(item -> item.getLevel().equals(subLevel)).collect(Collectors.toList());
            List<String> paramList = new ArrayList<>();
            //如果存在门店->即第四级区域
            if (CollectionUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_FOUR))) {
                return this.getStoreLevel(leafCodeList,paramList,listMap);
            }
            //如果存在区->即第三级区域
            if (CollectionUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_THREE))) {
                if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_ONE))) {
                    listMap.get(CommonConstants.AREA_LEVEL_ONE).forEach(item -> paramList.add(item.getCode()));
                    List<AreaDTO> cityCode = this.batchSearchByParentCode(paramList);
                    paramList.clear();
                    if(ObjectUtil.isNotEmpty(cityCode)){
                        cityCode.forEach(item->{paramList.add(item.getCode());});
                    }
                }
                if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_TWO))) {
                    listMap.get(CommonConstants.AREA_LEVEL_TWO).forEach(item -> paramList.add(item.getCode()));
                    return this.dealOtherLevel(leafCodeList, paramList);
                }else{
                    //根据二级区域获取第三级区域
                    return this.dealOtherLevel(leafCodeList, paramList);
                }
            }
            //如果存在市->即第二级区域
            if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_TWO))) {
                if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_ONE))) {
                    listMap.get(CommonConstants.AREA_LEVEL_ONE).forEach(item -> paramList.add(item.getCode()));
                    return this.dealOtherLevel(leafCodeList, paramList);
                }
            }
        }
        return areaCodeList;
    }

    /**
     * 处理除门店其余层级的返回值
     */
    public List<SalesPlanSelectDTO> dealOtherLevel(List<SalesPlanSelectDTO> leafCodeList,List<String> paramList){
        List<AreaDTO> areaDTOS = this.batchSearchByParentCode(paramList);
        if(ObjectUtil.isNotEmpty(areaDTOS)){
            areaDTOS.forEach(item->{
                SalesPlanSelectDTO selectDTO=new SalesPlanSelectDTO();
                selectDTO.setCode(item.getCode());
                selectDTO.setLevel(item.getLevel());
                leafCodeList.add(selectDTO);
            });
        }
        return leafCodeList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 处理有门店级别的区域类型
     */
    public List<SalesPlanSelectDTO> getStoreLevel(List<SalesPlanSelectDTO> leafCodeList,List<String> paramList,Map<Integer, List<SalesPlanSelectDTO>> listMap){

        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_ONE))) {
            paramList.clear();
            listMap.get(CommonConstants.AREA_LEVEL_ONE).forEach(item -> paramList.add(item.getCode()));
            PageInfo<StoreDTO> pageInfo = this.selectStoreByProvinceCode(paramList, 1, 9999);
            this.dealStore(leafCodeList,pageInfo);
        }
        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_TWO))) {
            paramList.clear();
            listMap.get(CommonConstants.AREA_LEVEL_TWO).forEach(item -> paramList.add(item.getCode()));
            PageInfo<StoreDTO> pageInfo = this.selectStoreByCityCode(paramList, 1, 9999);
            this.dealStore(leafCodeList,pageInfo);
        }
        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.AREA_LEVEL_THREE))) {
            paramList.clear();
            listMap.get(CommonConstants.AREA_LEVEL_THREE).forEach(item -> paramList.add(item.getCode()));
            PageInfo<StoreDTO> pageInfo = this.selectStoreByDistrictCode(paramList, 1, 9999);
            this.dealStore(leafCodeList,pageInfo);
        }
        return leafCodeList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 处理门店
     *
     * @param leafCodeList 叶代码列表
     * @param pageInfo     页面信息
     * @return {@link List<SalesPlanSelectDTO>}
     */
    private List<SalesPlanSelectDTO> dealStore(List<SalesPlanSelectDTO> leafCodeList,PageInfo<StoreDTO> pageInfo){
        if(CollectionUtil.isNotEmpty(pageInfo.getList())){
            pageInfo.getList().forEach(item->{
                SalesPlanSelectDTO selectDTO = new SalesPlanSelectDTO();
                selectDTO.setCode(item.getCode());
                selectDTO.setLevel(CommonConstants.AREA_LEVEL_FOUR);
                leafCodeList.add(selectDTO);
            });
        }
        return leafCodeList;
    }

    /**
     * 根据区域code获取下级区域信息
     *
     * @param parentCode
     * @return
     */
    public List<SalesPlanSelectDTO> getSubAreaCode(String parentCode) {
        log.info("根据区域code获取下级区域信息：parentCode：{}", parentCode);
        Response<List<SalesPlanSelectDTO>> response = baseDataRemote.getSubAreaCode(parentCode);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据区域级别查询区域信息
     *
     * @param level
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageInfo<AreaDTO> getAreaByLevels(List<Integer> level, Integer pageNum, Integer pageSize) {
        log.info("根据区域级别查询区域信息：level,pageNum,pageSize：{}", level + ",", pageNum + ",", pageSize);
        Response<PageInfo<AreaDTO>> response = baseDataRemote.getAreaByLevels(level, pageNum, pageSize);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }


    /**
     * 验证渠道code
     *
     * @param channelCodeList
     * @return
     */
    public Boolean verificationChannelCode(List<String> channelCodeList) {
        if (CollectionUtils.isEmpty(channelCodeList)) {
            return false;
        }
        Response<List<ChannelDTO>> response = baseDataRemote.listChannelCodeByList(channelCodeList);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return channelCodeList.size() == response.getData().size() && !CollectionUtils.isEmpty(channelCodeList);
    }

    /**
     * 根据地区name模糊查询地区信息（没有批量查询接口）
     *
     * @param provinceList
     * @return
     */
    public List<AreaDTO> listProvinceByList(List<String> provinceList) {
        List<AreaDTO> areaList = new ArrayList<>();
        provinceList.forEach(item -> {
            Response<List<AreaDTO>> response = baseDataRemote.listAreaInfoByName(item);
            if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
                throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
            }
            areaList.add(response.getData().get(0));
        });
        return areaList;
    }

    public List<AreaDTO> listByAreaName(String areaName){
        Response<List<AreaDTO>> response = baseDataRemote.listAreaInfoByName(areaName);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    /**
     * 验证销售组织Code
     *
     * @param salesOrgCodeList
     * @return
     */
    public List<SaleOrgDTO> verificationOrgCode(List<String> salesOrgCodeList) {
        List<SaleOrgDTO> saleOrgList = new ArrayList<>();
        salesOrgCodeList.forEach(item -> {
            Response<SaleOrgDTO> response = baseDataRemote.getSaleOrg(item);
            if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
                throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
            }
            saleOrgList.add(response.getData());
        });
        return saleOrgList;
    }

    /**
     * 查询所有公司信息
     *
     * @return {@link List< SaleOrgDTO >}
     */
    public List<SaleOrgDTO> listSaleOrg() {
        Response<List<SaleOrgDTO>> response = baseDataRemote.listSaleOrg();
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public List<ChannelDTO> queryByParentChannel(String parentChannel) {
        log.info("根据父渠道查询子渠道入参:parentChannel:{}", parentChannel);
        Response<List<ChannelDTO>> response = baseDataRemote.queryByParentChannel(parentChannel);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public List<ChannelDTO> queryByParentChannels(List<String> channelCodeList) {
        log.info("根据父渠道批量查询子渠道入参:channelCodeList；{}", channelCodeList);
        Response<List<ChannelDTO>> response = baseDataRemote.queryByParentChannels(channelCodeList);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public List<ChannelDTO> getChannelByLevel(Integer level) {
        log.info("根据渠道的等级查询渠道入参:level:{}", level);
        Response<List<ChannelDTO>> response = baseDataRemote.getChannelByLevel(level);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> listStore(StoreDTO storeSimpleParamDTO) {
        log.info("根据门店的信息查询门店入参:storeSimpleParamDTO:{}", storeSimpleParamDTO);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.listStore(storeSimpleParamDTO, 1, 9999);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> listStore(StoreDTO storeSimpleParamDTO, int pageNum, int pageSize) {
        log.info("根据门店的信息查询门店入参2:storeSimpleParamDTO:{}", storeSimpleParamDTO);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.listStore(storeSimpleParamDTO, pageNum, pageSize);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public List<AreaDTO> batchSearchByParentCode(List<String> parentCodes){
        log.info("批量根据parentCode获取所有下级入参:parentCodes:{}", parentCodes);
        Response<List<AreaDTO>> response = baseDataRemote.batchSearchByParentCode(parentCodes);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public List<AreaDTO> listAreaInfoByCode(List<String> codes) {
        log.info("根据code获取区域信息:codes:{}", codes);
        List<AreaDTO> areaList = new ArrayList<>();
        Response<List<AreaDTO>> response = baseDataRemote.listAreaInfoByCode(codes);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> selectStoreByAreaCode(SearchStoreParamDTO storeParamDTO,Integer pageNum,Integer pageSize){
        log.info("根据省市区code获取门店入参：storeParamDTO：{}", JSON.toJSONString(storeParamDTO),pageNum,pageSize);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.selectStoreByAreaCode(storeParamDTO, pageNum, pageSize);
        if(!response.getCode().equals(ResponseMsg.SUCCESS.getCode())){
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> selectStoreByProvinceCode(List<String> provinceCodeList, Integer pageNum, Integer pageSize){
        log.info("批量根据省code查询门店入参:provinceCodeList:{}", JSON.toJSONString(provinceCodeList),pageNum,pageSize);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.selectStoreByProvinceCode(provinceCodeList, pageNum, pageSize);
        if(!response.getCode().equals(ResponseMsg.SUCCESS.getCode())){
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> selectStoreByCityCode(List<String> cityCodeList, Integer pageNum, Integer pageSize){
        log.info("批量根据市code查询门店入参:provinceCodeList:{}", JSON.toJSONString(cityCodeList),pageNum,pageSize);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.selectStoreByCityCode(cityCodeList, pageNum, pageSize);
        if(!response.getCode().equals(ResponseMsg.SUCCESS.getCode())){
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    public PageInfo<StoreDTO> selectStoreByDistrictCode(List<String> districtCodeList, Integer pageNum, Integer pageSize){
        log.info("批量根据区code查询门店入参:provinceCodeList:{}", JSON.toJSONString(districtCodeList),pageNum,pageSize);
        Response<PageInfo<StoreDTO>> response = baseDataRemote.selectStoreByDistrictCode(districtCodeList, pageNum, pageSize);
        if(!response.getCode().equals(ResponseMsg.SUCCESS.getCode())){
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据地区编码获取地区层级信息
     *
     * @param areaList
     * @return
     */
    public List<AreaLevelDTO> listRelationByArea(List<String> areaList) {
        log.info("根据地区编码获取地区层级信息入参:areaList:{}", JSON.toJSONString(areaList));
        Response<List<AreaLevelDTO>> response = baseDataRemote.listRelationByArea(areaList);
        if (!response.getCode().equals(ResponseMsg.SUCCESS.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2005.getCode(), ResponseMsg.EXCEPTION_2005.getMsg());
        }
        return response.getData();
    }
}
